package com.dolphin.aiagentplatform.utils;

import com.dolphin.aiagentplatform.constant.ResponseCodeConst;
import com.dolphin.aiagentplatform.exception.BusinessException;
import com.dolphin.aiagentplatform.model.vo.user.UserVO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 令牌管理工具类
 * 提供基于JWT和Redis的分布式用户会话管理相关功能
 */
@Slf4j
@Component
public class TokenManager {

    /**
     * 认证头名称
     */
    private static final String AUTH_HEADER = "Authorization";

    /**
     * 令牌前缀
     */
    private static final String TOKEN_PREFIX = "Bearer ";

    /**
     * 注入RedisUtils
     */
    @Resource
    private RedisUtils redisUtils;
    
    /**
     * 注入JwtUtils
     */
    @Resource
    private JwtUtils jwtUtils;

    /**
     * 保存用户登录令牌
     *
     * @param response HTTP响应
     * @param userVO   用户视图对象
     * @return 生成的JWT令牌
     */
    public String createUserToken(HttpServletResponse response, UserVO userVO) {
        if (userVO == null || userVO.getId() == null) {
            throw new BusinessException(ResponseCodeConst.PARAMS_ERROR, "用户信息不完整");
        }

        // 使用注入的jwtUtils实例生成JWT令牌
        String token = jwtUtils.createToken(userVO);

        // 将用户信息存入Redis
        redisUtils.setUserToken(token, userVO);

        // 设置认证头
        response.setHeader(AUTH_HEADER, jwtUtils.getAuthHeader(token));

        log.debug("用户令牌已创建，用户ID:{}, 令牌:{}", userVO.getId(), token);
        return token;
    }

    /**
     * 获取当前登录用户信息
     *
     * @param request HTTP请求
     * @return 当前登录用户信息，如果未登录则返回null
     */
    public UserVO getLoginUser(HttpServletRequest request) {
        if (request == null) {
            return null;
        }

        // 从请求头中获取Token
        String token = getTokenFromRequest(request);
        if (token == null) {
            log.debug("请求中未找到令牌");
            return null;
        }

        // 验证令牌有效性
        if (!jwtUtils.validateToken(token)) {
            // 令牌无效，从Redis中删除
            log.debug("令牌验证失败: {}", token);
            redisUtils.deleteUserToken(token);
            return null;
        }

        // 从Redis中获取用户信息
        UserVO userVO = redisUtils.getUserToken(token);
        if (userVO == null) {
            log.debug("Redis中未找到令牌对应的用户信息: {}", token);
            return null;
        }

        // 刷新令牌过期时间
        redisUtils.refreshUserToken(token);

        log.debug("成功获取用户信息: {}", userVO);
        return userVO;
    }

    /**
     * 获取当前登录用户信息（如果未登录则抛出异常）
     *
     * @param request HTTP请求
     * @return 当前登录用户信息
     * @throws BusinessException 如果用户未登录
     */
    public UserVO getAndCheckLoginUser(HttpServletRequest request) {
        UserVO userVO = getLoginUser(request);
        if (userVO == null) {
            throw new BusinessException(ResponseCodeConst.NOT_LOGIN_ERROR, "未登录");
        }
        return userVO;
    }

    /**
     * 移除用户令牌
     *
     * @param request  HTTP请求
     * @param response HTTP响应
     */
    public void removeUserToken(HttpServletRequest request, HttpServletResponse response) {
        if (request == null) {
            return;
        }

        String token = getTokenFromRequest(request);
        if (token == null) {
            return;
        }

        // 从Redis中删除令牌
        redisUtils.deleteUserToken(token);

        // 清除认证头
        if (response != null) {
            response.setHeader(AUTH_HEADER, "");
        }

        log.debug("用户令牌已移除，令牌:{}", token);
    }

    /**
     * 刷新用户令牌
     *
     * @param request HTTP请求
     * @return 是否成功
     */
    public boolean refreshUserToken(HttpServletRequest request) {
        String token = getTokenFromRequest(request);
        if (token == null) {
            return false;
        }
        return redisUtils.refreshUserToken(token);
    }

    /**
     * 从请求中获取令牌
     *
     * @param request HTTP请求
     * @return 令牌字符串或null
     */
    public String getTokenFromRequest(HttpServletRequest request) {
        String header = request.getHeader(AUTH_HEADER);
        if (header != null && header.startsWith(TOKEN_PREFIX)) {
            return header.substring(7);
        }
        return null;
    }

    /**
     * 检查用户是否在线
     *
     * @param userId 用户ID
     * @return 是否在线
     */
    public boolean isUserOnline(Long userId) {
        // 这个方法的实现相对复杂，需要在Redis中查找所有的用户令牌
        // 简化版本可以通过单独维护一个用户在线状态的Redis键值对来实现
        return false;
    }
} 